﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Internal;
using System.Globalization;
using System.Runtime.InteropServices;

namespace System.ComponentModel.Composition
{
    internal static class MetadataViewProvider
    {
        public  static TMetadataView GetMetadataView<TMetadataView>(IDictionary<string, object> metadata)
        {
            Type metadataViewType = typeof(TMetadataView);

            // If the Metadata dictionary is cast compatible with the passed in type
            if (metadataViewType.IsAssignableFrom(typeof(IDictionary<string, object>)))
            {
                return (TMetadataView)metadata;
            }
            // otherwise is it a metadata view
            else if (metadataViewType.IsInterface)
            {
                Type proxyType = MetadataViewGenerator.GenerateView(metadataViewType);
                return (TMetadataView)Activator.CreateInstance(proxyType, new object[] { metadata });
            }
            // otherwise look for a constructor that takes an IDictionary<string, object>
            else
            {
                try
                {
                    TMetadataView value = (TMetadataView)Activator.CreateInstance(metadataViewType, new object[] { metadata });
                    return value;
                }
                catch(Exception e)
                {
                    if(e is OutOfMemoryException
                    || e is COMException
                    || e is SEHException
                    || e is ExecutionEngineException)
                    {
                        throw;
                    }

                    // Not a fatal exception the Developer selected the wrong Metadata view type so we must throw an InvalidOperationException
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Strings.CannotCreateMetadataView, metadataViewType.FullName, "TMetadataView"), e);
                }
            }

        }

        public static bool IsViewTypeValid(Type metadataViewType)
        {
            Assumes.NotNull(metadataViewType);

            // If the Metadata dictionary is cast compatible with the passed in type
            if (ExportServices.IsDefaultMetadataViewType(metadataViewType)
            ||  metadataViewType.IsInterface
            ||  ExportServices.IsDictionaryConstructorViewType(metadataViewType))
            {
                return true;
            }

            return false;
        }
    }
}
